﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using XRM.Security.DataAccess.Models;
using XRM.Security.WebUI.Enums;
using XRM.Security.WebUI.Helpers;
using XRM.Security.WebUI.Models.InfoSystem;

namespace XRM.Security.WebUI.Controllers
{
    [System.Web.Mvc.Authorize]
    public class InfoSystemController : BaseController
    {
        [System.Web.Mvc.Authorize(Roles = "Administrator, InfoSystemViewer, InfoSystemEditor")]
        public ActionResult Index()
        { 
            List<InfoSystem> InfoSystems = InfoSystemRepository.GetAll().ToList();
            List<InfoSystemModel> model = new List<InfoSystemModel>();

            foreach (var InfoSystem in InfoSystems)
            {
                var infoSystemModel = new InfoSystemModel(InfoSystem);
                infoSystemModel.CanDelete = ((!RequestWorkKindParamRepository.GetAll(x => x.InfoSystemId == infoSystemModel.Id).Any()) && (!UserInfoSystemRepository.GetAll(x => x.InfoSystemId == infoSystemModel.Id).Any()));
                model.Add(infoSystemModel);
            }

            return View(model);
        }
        
        [System.Web.Mvc.HttpGet]
        [System.Web.Mvc.Authorize(Roles = "Administrator, InfoSystemViewer, InfoSystemEditor")]
        public ActionResult Edit(int? id)
        {
            InfoSystemModel model = new InfoSystemModel(id != null ? InfoSystemRepository.Get(id) : null);
            if ((id != null) && (model.Id == null))
                throw new HttpException(404, "Информационная система не найдена");
            else if ((id == null) && (!Permission.AllowInfoSystemEdit()))
                throw new HttpException(404, "Информационная система не найдена");

            /*if (model.IsEdit)
                model.FilePath = Path.Combine(FilesFolder, "SystemInfo", model.Id.Value.ToString());
            else
                model.FilePath = Path.Combine(FilesFolder, "SystemInfo", "New", Session.SessionID);*/

            string filePath = Path.Combine(FilesFolder, "SystemInfo", "New", Session.SessionID);
            Utils.CreateOrClearDirectory(filePath);

            if (model.InMaintenance)
                model.DateOut = DateTime.Today.Date;
            model.FileUploadUrl = Url.Action("UploadFiles", "InfoSystem");
            model.ReadOnly = !Permission.AllowInfoSystemEdit() || (model.IsEdit && !model.InMaintenance);

            return View(model);
        }

        [System.Web.Mvc.HttpPost]
        [System.Web.Mvc.Authorize(Roles = "Administrator, InfoSystemEditor")]
        public ActionResult Edit(InfoSystemModel model)
        {
            model.FileUploadUrl = Url.Action("UploadFiles", "InfoSystem");
            model.GetFiles(InfoSystemFileRepository.GetAll(x => x.InfoSystemId == model.Id).ToList());
            if (!ModelState.IsValid)
            {
                ShowAlert(AlertType.Error, GetModelErrors());
                return View(model);
            }

            string checkValue = model.InfoSystemName;
            if (InfoSystemRepository.Get(x => (x.InfoSystemName.ToLower().Equals(checkValue) && (x.InfoSystemId != model.Id))) != null)
            {
                ShowAlert(AlertType.Error, string.Format("Информационная система с названием '{0}' уже существует", model.InfoSystemName));
                return View(model);
            }

            bool needRevoke = false;
            InfoSystem infoSystem;
            if (model.IsEdit)
            {
                infoSystem = InfoSystemRepository.Get(model.Id);
                if (infoSystem == null || !infoSystem.InMaintenance)
                    throw new HttpResponseException(HttpStatusCode.BadRequest);

                if ((infoSystem.InMaintenance) && (!model.InMaintenance))
                {
                    needRevoke = true;
                    infoSystem.DateOut = DateTime.Today.Date;
                }
                infoSystem.InMaintenance = model.InMaintenance;
            }
            else
            {
                infoSystem = new InfoSystem
                    {
                        DateIn = DateTime.Today,
                        InMaintenance = true
                    };
            }
            infoSystem.InfoSystemName = model.InfoSystemName;
            infoSystem.DomainGroup = model.DomainGroup;
            infoSystem.Operator = model.Operator;
            infoSystem.OperatorContact = model.OperatorContact;
            infoSystem.Developer = model.Developer;
            infoSystem.Support = model.Support;
            infoSystem.Comment = model.Comment;

            if (!model.IsEdit)
                InfoSystemRepository.Add(infoSystem);

            // Переносим файлы в рабочую папку
            //string filePath = Path.Combine(FilesFolder, "SystemInfo", infoSystem.InfoSystemId.ToString());
            //if (!Directory.Exists(filePath))
            //    Directory.CreateDirectory(filePath);

            //todo: избавиться от временных файлов
            string fileTmp = Path.Combine(FilesFolder, "SystemInfo", "New", Session.SessionID);
            string[] files = Directory.GetFiles(fileTmp);
            foreach (string file in files)
            {
                try
                {
                    //string destFileName = Path.GetFileName(file);
                    //destFileName = Utils.GetSafeFileName(filePath, destFileName);
                    //System.IO.File.Move(file, Path.Combine(filePath, destFileName));

                    InfoSystemFile fileDb = new InfoSystemFile();
                    fileDb.InfoSystemId = infoSystem.InfoSystemId;
                    fileDb.UploadDate = DateTime.Now;
                    fileDb.FileName = Path.GetFileName(file);
                    fileDb.FileData = System.IO.File.ReadAllBytes(file);
                    infoSystem.Files.Add(fileDb);

                    System.IO.File.Delete(file);
                }
                catch (Exception ex)
                {
                }
            }
            Directory.Delete(fileTmp);

            InfoSystemRepository.Update(infoSystem);
            if (needRevoke)
            {
                List<UserInfoSystem> lstRevoke = UserInfoSystemRepository.GetAll(x => (x.InfoSystemId == infoSystem.InfoSystemId) && (!x.RevokeDate.HasValue)).ToList();
                foreach (UserInfoSystem item in lstRevoke)
                {
                    item.RevokeDate = DateTime.Now;
                    item.RevokeSystemUserId = UserPrincipal.UserId;
                    item.RevokeReason = "Система выведена из эксплуатации";
                    UserInfoSystemRepository.Update(item);
                }
            }

            if (model.IsEdit)
                ShowAlert(AlertType.Success, "Информационная система отредактирована успешно");
            else
                ShowAlert(AlertType.Success, "Информационная система создана успешно");
            
            return RedirectToAction("Index");
        }

        [System.Web.Mvc.HttpPost]
        [System.Web.Mvc.Authorize(Roles = "Administrator, InfoSystemEditor")]
        public ActionResult UploadFiles()
        {
            string filePath = Path.Combine(FilesFolder, "SystemInfo", "New", Session.SessionID);

            try
            {
                for (int i = 0; i < Request.Files.Count; ++i)
                {
                    HttpPostedFileBase postedFile = Request.Files[i];

                    var stream = postedFile.InputStream;
                    string fileSavePath = Path.Combine(filePath, Utils.GetSafeFileName(filePath, Path.GetFileName(postedFile.FileName)));

                    var buffer = new byte[stream.Length];
                    stream.Read(buffer, 0, buffer.Length);
                    System.IO.File.WriteAllBytes(fileSavePath, buffer);
                }
            }
            catch (Exception ex)
            {
                return Json(new { success = false, message = ex.Message }, "application/json");
            }

            return Json(new { success = true }, "text/html");
        }

        [System.Web.Mvc.Authorize(Roles = "Administrator, InfoSystemEditor")]
        public ActionResult Delete(int id)
        {
            InfoSystem infoSystem = InfoSystemRepository.Get(id);

            if (infoSystem != null)
            {
                // TODO refactoring проверить связи
                InfoSystemRepository.Delete(infoSystem);

                /*string filePath = Path.Combine(FilesFolder, "SystemInfo", infoSystem.InfoSystemId.ToString());
                if (Directory.Exists(filePath))
                {
                    Utils.CreateOrClearDirectory(filePath);
                    Directory.Delete(filePath);
                }*/

                ShowAlert(AlertType.Success, "Информационная система удалена успешно");
            }
            else
            {
                ShowAlert(AlertType.Error, "Информационная система не найдена");
            }

            return RedirectToAction("Index");
        }

        [System.Web.Mvc.Authorize(Roles = "Administrator, InfoSystemEditor")]
        public ActionResult DeleteFile(int id)
        {
            InfoSystemFile infoSystemFile = InfoSystemFileRepository.Get(id);
            int infoSystemId = infoSystemFile.InfoSystemId;

            if (infoSystemFile != null)
            {
                /*string filePath = Path.Combine(FilesFolder, "SystemInfo", infoSystemId.ToString());
                if (System.IO.File.Exists(Path.Combine(filePath, infoSystemFile.FileName)))
                {
                    try
                    {
                        System.IO.File.Delete(Path.Combine(filePath, infoSystemFile.FileName));
                    }
                    catch(Exception ex)
                    {
                    }
                }*/
                
                InfoSystemFileRepository.Delete(infoSystemFile);
                ShowAlert(AlertType.Success, "Паспорт или положение о системе удалено успешно");
            }
            else
            {
                ShowAlert(AlertType.Error, "Паспорт или положение о системе не найдено");
            }

            return RedirectToAction("Edit", new { id = infoSystemId });
        }

        [System.Web.Mvc.HttpGet]
        [System.Web.Mvc.Authorize(Roles = "Administrator, InfoSystemViewer, InfoSystemEditor")]
        public FileStreamResult DownloadInfoSystemFile(int id)
        {
            InfoSystemFile infoSystemFile = InfoSystemFileRepository.Get(id);

            if (infoSystemFile != null)
            {
                Stream fileStream = new MemoryStream(infoSystemFile.FileData);
                FileStreamResult fsr = new FileStreamResult(fileStream, "application/octet-stream");
                fsr.FileDownloadName = Path.GetFileName(infoSystemFile.FileName);
                return fsr;
            }
            else
                return null;
        }
    }
}
